﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.IO;
using Moq;
using AWSS3ToAzureBlob;

namespace AWSS3ToAzureBlob.Test
{
    [TestClass]
    public class ProgramUnitTest
    {
        private Mock<IAWSS3Facade> _awsS3Mock = null;
        private Mock<IAzureStorageBlobFacade> _azureStorageBlobMock = null;
        private Mock<IFileMigrator> _fileMigrator = null;

        TextWriter _oldConsole;
        StringWriter _newConsole;

        private void MockInitialize()
        {
            _awsS3Mock = new Mock<IAWSS3Facade>();
            _azureStorageBlobMock = new Mock<IAzureStorageBlobFacade>();
            _fileMigrator = new Mock<IFileMigrator>();
        }

        private void ConsoleInitialize()
        {
            _oldConsole = Console.Out;
            _newConsole = new StringWriter();
            Console.SetOut(_newConsole);
        }

        [TestInitialize]
        public void Initialize()
        {
            MockInitialize();
            ConsoleInitialize();
        }


        [TestCleanup]
        public void Cleanup()
        {
            MockCleanup();
            ConsoleCleanup();
        }

        private void MockCleanup()
        {
            _awsS3Mock = null;
            _azureStorageBlobMock = null;
            _fileMigrator = null;
        }

        private void ConsoleCleanup()
        {
            Console.SetOut(_oldConsole);
            Console.Write(_newConsole);
        }


        [TestMethod]
        public void InvalidParametersNullArgs()
        {
            Program.MainWithFacades(null,
                _fileMigrator.Object,
                _awsS3Mock.Object,
                _azureStorageBlobMock.Object);

            Assert.IsTrue(_newConsole.ToString().Contains(Messages.InvalidParameters));
            _fileMigrator.Verify(m => m.Initialize(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<IAWSS3Facade>(), It.IsAny<IAzureStorageBlobFacade>()), Times.Never());
            _fileMigrator.Verify(m => m.MigrateFiles(), Times.Never());
        }

        [TestMethod]
        public void InvalidParametersEmptyArgs()
        {
            Program.MainWithFacades(new string[0],
                _fileMigrator.Object,
                _awsS3Mock.Object,
                _azureStorageBlobMock.Object);

            Assert.IsTrue(_newConsole.ToString().Contains(Messages.InvalidParameters));
            _fileMigrator.Verify(m => m.Initialize(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<IAWSS3Facade>(), It.IsAny<IAzureStorageBlobFacade>()), Times.Never());
            _fileMigrator.Verify(m => m.MigrateFiles(), Times.Never());
        }

        [TestMethod]
        public void WrongNumberOfParameters()
        {
            Program.MainWithFacades(new string[3],
                _fileMigrator.Object,
                _awsS3Mock.Object,
                _azureStorageBlobMock.Object);

            Assert.IsTrue(_newConsole.ToString().Contains(Messages.InvalidParameters));
            _fileMigrator.Verify(m => m.Initialize(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<IAWSS3Facade>(), It.IsAny<IAzureStorageBlobFacade>()), Times.Never());
            _fileMigrator.Verify(m => m.MigrateFiles(), Times.Never());
        }

        [TestMethod]
        public void InvalidParameter()
        {
            string[] args = new string[14];
            args[0] = "-azkey";
            args[1] = "1234";
            args[2] = "-invalidparameter";
            args[3] = "invalidvalue";

            Program.MainWithFacades(args,
                _fileMigrator.Object,
                _awsS3Mock.Object,
                _azureStorageBlobMock.Object);

            Assert.IsTrue(_newConsole.ToString().Contains(Messages.InvalidParameters));
            _fileMigrator.Verify(m => m.Initialize(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<IAWSS3Facade>(), It.IsAny<IAzureStorageBlobFacade>()), Times.Never());
            _fileMigrator.Verify(m => m.MigrateFiles(), Times.Never());
        }

        [TestMethod]
        public void DuplicateAzKeyParameter()
        {
            string[] args = new string[14];
            args[0] = "-azkey"; //duplicated param
            args[1] = "1234";
            args[2] = "-azaccount";
            args[3] = "account";
            args[4] = "-azkey"; //duplicated param
            args[5] = "5678";

            Program.MainWithFacades(args,
                _fileMigrator.Object,
                _awsS3Mock.Object,
                _azureStorageBlobMock.Object);

            Assert.IsTrue(_newConsole.ToString().Contains(Messages.InvalidParameters));
            _fileMigrator.Verify(m => m.Initialize(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<IAWSS3Facade>(), It.IsAny<IAzureStorageBlobFacade>()), Times.Never());
            _fileMigrator.Verify(m => m.MigrateFiles(), Times.Never());
        }

        [TestMethod]
        public void DuplicateAzContainerParameter()
        {
            string[] args = new string[14];
            args[0] = "-azcontainer"; //duplicated param
            args[1] = "container1";
            args[2] = "-azaccount";
            args[3] = "account";
            args[4] = "-azcontainer"; //duplicated param
            args[5] = "container2";

            Program.MainWithFacades(args,
                _fileMigrator.Object,
                _awsS3Mock.Object,
                _azureStorageBlobMock.Object);

            Assert.IsTrue(_newConsole.ToString().Contains(Messages.InvalidParameters));
            _fileMigrator.Verify(m => m.Initialize(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<IAWSS3Facade>(), It.IsAny<IAzureStorageBlobFacade>()), Times.Never());
            _fileMigrator.Verify(m => m.MigrateFiles(), Times.Never());
        }

        [TestMethod]
        public void DuplicateAwsKeyIdParameter()
        {
            string[] args = new string[14];
            args[0] = "-awskeyid"; //duplicated param
            args[1] = "1234";
            args[2] = "-azaccount";
            args[3] = "account";
            args[4] = "-awskeyid"; //duplicated param
            args[5] = "5678";

            Program.MainWithFacades(args,
                _fileMigrator.Object,
                _awsS3Mock.Object,
                _azureStorageBlobMock.Object);

            Assert.IsTrue(_newConsole.ToString().Contains(Messages.InvalidParameters));
            _fileMigrator.Verify(m => m.Initialize(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<IAWSS3Facade>(), It.IsAny<IAzureStorageBlobFacade>()), Times.Never());
            _fileMigrator.Verify(m => m.MigrateFiles(), Times.Never());
        }

        [TestMethod]
        public void DuplicateAwsKeyParameter()
        {
            string[] args = new string[14];
            args[0] = "-awskey"; //duplicated param
            args[1] = "awskey1";
            args[2] = "-azaccount";
            args[3] = "account";
            args[4] = "-awskey"; //duplicated param
            args[5] = "awskey2";

            Program.MainWithFacades(args,
                _fileMigrator.Object,
                _awsS3Mock.Object,
                _azureStorageBlobMock.Object);

            Assert.IsTrue(_newConsole.ToString().Contains(Messages.InvalidParameters));
            _fileMigrator.Verify(m => m.Initialize(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<IAWSS3Facade>(), It.IsAny<IAzureStorageBlobFacade>()), Times.Never());
            _fileMigrator.Verify(m => m.MigrateFiles(), Times.Never());
        }

        [TestMethod]
        public void DuplicateAwsBucketParameter()
        {
            string[] args = new string[14];
            args[0] = "-awsbucket"; //duplicated param
            args[1] = "bucket1";
            args[2] = "-azaccount";
            args[3] = "account";
            args[4] = "-awsbucket"; //duplicated param
            args[5] = "bucket2";

            Program.MainWithFacades(args,
                _fileMigrator.Object,
                _awsS3Mock.Object,
                _azureStorageBlobMock.Object);

            Assert.IsTrue(_newConsole.ToString().Contains(Messages.InvalidParameters));
            _fileMigrator.Verify(m => m.Initialize(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<IAWSS3Facade>(), It.IsAny<IAzureStorageBlobFacade>()), Times.Never());
            _fileMigrator.Verify(m => m.MigrateFiles(), Times.Never());
        }

        [TestMethod]
        public void DuplicateAwsExpiryParameter()
        {
            string[] args = new string[14];
            args[0] = "-awsexpiry"; //duplicated param
            args[1] = "60";
            args[2] = "-azaccount";
            args[3] = "account";
            args[4] = "-awsexpiry"; //duplicated param
            args[5] = "120";

            Program.MainWithFacades(args,
                _fileMigrator.Object,
                _awsS3Mock.Object,
                _azureStorageBlobMock.Object);

            Assert.IsTrue(_newConsole.ToString().Contains(Messages.InvalidParameters));
            _fileMigrator.Verify(m => m.Initialize(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<IAWSS3Facade>(), It.IsAny<IAzureStorageBlobFacade>()), Times.Never());
            _fileMigrator.Verify(m => m.MigrateFiles(), Times.Never());
        }

        [TestMethod]
        public void DuplicateAzAccountParameter()
        {
            string[] args = new string[14];
            args[0] = "-azaccount"; //duplicated param
            args[1] = "account";
            args[2] = "-azkey";
            args[3] = "1234";
            args[4] = "-azaccount"; //duplicated param
            args[5] = "account";

            Program.MainWithFacades(args,
                _fileMigrator.Object,
                _awsS3Mock.Object,
                _azureStorageBlobMock.Object);

            Assert.IsTrue(_newConsole.ToString().Contains(Messages.InvalidParameters));
            _fileMigrator.Verify(m => m.Initialize(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<IAWSS3Facade>(), It.IsAny<IAzureStorageBlobFacade>()), Times.Never());
            _fileMigrator.Verify(m => m.MigrateFiles(), Times.Never());
        }


        [TestMethod]
        public void CorrectParameters()
        {
            string[] args = new string[14];
            args[0] = "-azkey";
            args[1] = "azkey";
            args[2] = "-azaccount";
            args[3] = "azaccount";
            args[4] = "-azcontainer";
            args[5] = "azcontainer";
            args[6] = "-awskeyid";
            args[7] = "awskeyid";
            args[8] = "-awskey";
            args[9] = "awskey";
            args[10] = "-awsbucket";
            args[11] = "awsbucket";
            args[12] = "-awsexpiry";
            args[13] = "60";

            Program.MainWithFacades(args,
                _fileMigrator.Object,
                _awsS3Mock.Object,
                _azureStorageBlobMock.Object);

            _fileMigrator.Verify(m => m.Initialize(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<IAWSS3Facade>(), It.IsAny<IAzureStorageBlobFacade>()), Times.Once());
            _fileMigrator.Verify(m => m.MigrateFiles(), Times.Once());
        }

        [TestMethod]
        public void FileMigratorException()
        {
            string[] args = new string[14];
            args[0] = "-azkey";
            args[1] = "azkey";
            args[2] = "-azaccount";
            args[3] = "azaccount";
            args[4] = "-azcontainer";
            args[5] = "azcontainer";
            args[6] = "-awskeyid";
            args[7] = "awskeyid";
            args[8] = "-awskey";
            args[9] = "awskey";
            args[10] = "-awsbucket";
            args[11] = "awsbucket";
            args[12] = "-awsexpiry";
            args[13] = "60";

            _fileMigrator.Setup(m => m.MigrateFiles())
                .Throws(new Exception(Messages.AWSS3ConnectionIssues));

            Program.MainWithFacades(args,
                _fileMigrator.Object,
                _awsS3Mock.Object,
                _azureStorageBlobMock.Object);

            Assert.IsTrue(_newConsole.ToString().Contains(Messages.AWSS3ConnectionIssues));
            _fileMigrator.Verify(m => m.Initialize(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<IAWSS3Facade>(), It.IsAny<IAzureStorageBlobFacade>()), Times.Once());
            _fileMigrator.Verify(m => m.MigrateFiles(), Times.Once());
        }

        [TestMethod]
        public void DisplayHelp()
        {
            Program.MainWithFacades(new string[]{"-h"},
                _fileMigrator.Object,
                _awsS3Mock.Object,
                _azureStorageBlobMock.Object);

            Assert.IsTrue(_newConsole.ToString().Contains(Messages.HelpMessage));
            _fileMigrator.Verify(m => m.Initialize(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<IAWSS3Facade>(), It.IsAny<IAzureStorageBlobFacade>()), Times.Never());
            _fileMigrator.Verify(m => m.MigrateFiles(), Times.Never());
        }
    }
}